#include "ir_control.h"
#include "Infrared_code.h"
#include "delay.h"
#include "ir_decode.h"
#include "w55mh32_gpio.h"
#include "w55mh32_tim.h"
#include "stdio.h"
#include "ir_defs.h"
#include "w55mh32_rcc.h"

// Key map
unsigned char g_operation_list[] = {2, 0, 3, 1, 9, 10};
// Used to store decoded time sequence data
unsigned short g_user_data[USER_DATA_SIZE] = {0};
// Used to store the length of the time sequence before decoding
unsigned short g_length = 0;

/**
 * @brief  Start IR transmission
 * @param  void
 * @retval NULL
 */
static void run_ir()
{
    for (unsigned short i = 0; i < g_length; i++)
    {
        if (!(i % 2))
        {
            TIM_SetCompare4(TIM2, 1912);
        }
        else
        {
            TIM_SetCompare4(TIM2, 0);
        }
        delay_us(g_user_data[i]);
    }

    TIM_SetCompare4(TIM2, 0);

    delay_us(40000);
}

/**
 * @brief  decode by air conditioner brand and model
 * @param  brand brand
 * @param  type model
 * @param  operation operation
 * @param  ac_status AC status
 * @retval NULL
 */
static void get_ir_code(unsigned char brand, unsigned char type, unsigned char operation, t_remote_ac_status *ac_status)
{
    unsigned char *number_point = NULL;
    unsigned short *length_point = NULL;

    switch (brand)
    {
    case 0:
    {
        number_point = g_gree[type];
        length_point = g_gree_length;
        break;
    }
    case 1:
    {
        number_point = g_midea[type];
        length_point = g_midea_length;
        break;
    }
    case 2:
    {
        number_point = g_haier[type];
        length_point = g_haier_length;
        break;
    }
    default:
        break;
    }

    ir_binary_open(1, 1, number_point, length_point[type]);

    g_length = ir_decode(g_operation_list[operation], g_user_data, ac_status, 0);

    if (g_length == 0)
    {
        printf("Decode error");
    }

    ir_close();

    printf("g_length:%d\r\n", g_length);

    //    for(unsigned short i = 0; i < length; i++)
    //			printf("%d,", g_user_data[i]);
}

/**
 * @brief  control AC
 * @param  brand brand
 * @param  type model
 * @param  operation operation
 * @param  ac_status ac status
 * @retval NULL
 */
void ir_control(unsigned char brand, unsigned char type, unsigned char operation, t_remote_ac_status *ac_status)
{
    get_ir_code(brand, type, operation, ac_status);

    run_ir();
}

/**
 * @brief  infraRed GPIO init
 * @param  void
 * @retval NULL
 */
static void gpio_configuration(void)
{
    GPIO_InitTypeDef gpio_init_structure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    gpio_init_structure.GPIO_Pin = GPIO_Pin_3; // TIM_CH4
    gpio_init_structure.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio_init_structure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio_init_structure);
}

/**
 * @brief  infred pwm init
 * @param  void
 * @retval NULL
 */
static void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = 5736 - 1; // 218Mhz/5736≈38Khz
    TIM_TimeBaseStructure.TIM_Prescaler = 1 - 1; // 218Mhz/1=218Mhz
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    // Configure PWM mode
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1912; // Duty cycle calculation
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC4Init(TIM2, &TIM_OCInitStructure);

    TIM_Cmd(TIM2, ENABLE);
    TIM_SetCompare4(TIM2, 0);
}

/**
 * @brief  infrared init
 * @param  void
 * @retval NULL
 */
void ir_config(void)
{
    gpio_configuration();
    TIM_Configuration();
}
